package com.yunxin.core.utils.infra.utils;

import java.security.SecureRandom;
import java.util.Random;

/**
 * @author zero°
 * @since 2023-06-03
 */
public enum PromotionCodeUtils {

    /**
     * 实列
     */
    X;

    /**
     * 自定义进制(0,1没有加入,容易与o,l混淆)，数组顺序可进行调整增加反推难度，A用来补位因此此数组不包含A，共40个字符。
     */
    private static final char[] PROMOTION_BASE = new char[]{'9', 'q', 'a', 'C', 'b', '7', 'P','H', 'd', 'V', 'E', '8', '5', 'I', 'K', '3',
            'M', 'S', 'e', '2', 'D', 'N', 'f', '6', 'B', 'h', 'G', 'Q', 't', 'Z', 'X','J', 'U', 'F', 'R', '4', 'W', 'Y', 'L', 'T'};

    /**
     * A补位字符，不能与自定义重复
     */
    private static final char SUFFIX_CHAR = 'A';

    /**
     * 生成邀请码最小长度
     */
    private static final int CODE_LEN = 6;

    /**
     * ID转换为推广码
     * @param id id
     * @return promotionCode
     */
    public String idToPromotionCode(Long id) {
        return idToCode(id, PROMOTION_BASE.length, PROMOTION_BASE);
    }


    /**
     * 邀请码解析出ID<br/>
     * 基本操作思路恰好与idToCode反向操作。
     * @param code code
     * @return id
     */
    public Long promotionCodeToId(String code) {
        return codeToId(code, PROMOTION_BASE.length, PROMOTION_BASE);
    }



    /**
     * id转code
     *
     * @param id id
     * @param length length
     * @param chars chars
     * @return java.lang.String
     */
    private String idToCode(Long id, int length, char[] chars){
        char[] buf = new char[length];
        int charPos = length;
        // 当id除以数组长度结果大于0，则进行取模操作，并以取模的值作为数组的坐标获得对应的字符
        while (id / length > 0) {
            int index = (int) (id % length);
            buf[--charPos] = chars[index];
            id /= length;
        }
        buf[--charPos] = chars[(int) (id % length)];
        // 将字符数组转化为字符串
        String result = new String(buf, charPos, length - charPos);

        // 长度不足指定长度则随机补全
        int len = result.length();
        if (len < CODE_LEN) {
            StringBuilder sb = new StringBuilder();
            sb.append(SUFFIX_CHAR);
            Random random = new SecureRandom();
            // 去除SUFFIX_CHAR本身占位之后需要补齐的位数
            for (int i = 0; i < CODE_LEN - len - 1; i++) {
                sb.append(chars[random.nextInt(length)]);
            }
            result += sb.toString();
        }
        return result;
    }

    private Long codeToId(String code, int length, char[] chars) {
        char[] charArray = code.toCharArray();
        long result = 0L;
        for (int i = 0; i < charArray.length; i++) {
            int index = 0;
            for (int j = 0; j < length; j++) {
                if (charArray[i] == chars[j]) {
                    index = j;
                    break;
                }
            }
            if (charArray[i] == SUFFIX_CHAR) {
                break;
            }
            if (i > 0) {
                result = result * length + index;
            } else {
                result = index;
            }
        }
        return result;
    }

}
